[HNOI2012]永无乡

2019-12-08
HNOI

题意

对于一些点,支持连边和求联通块中第k重要的点

题解

动态开点权值线段树,线段树上合并

询问的时候二分即可

调试记录

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
#include <cstdio>
#define LS a[a[cur].ls]
#define RS a[a[cur].rs]
const int maxn = 1e5 + 5;
using namespace std;
struct T{
struct A{
int ls, rs, v, l, r;
}a[maxn * 40];
int rt[maxn], tot;
T(){tot = 0;}
void upd(int cur, int l, int r, int p){
a[cur].l = l, a[cur].r = r;
if (l == r){
a[cur].v = 1;
return;
}
int mid = l + r >> 1;
if (p <= mid){
if (!a[cur].ls) a[cur].ls = ++tot;
upd(a[cur].ls, l, mid, p);
}
else{
if (!a[cur].rs) a[cur].rs = ++tot;
upd(a[cur].rs, mid + 1, r, p);
}
a[cur].v = LS.v + RS.v;
}
int Merge(int cur, int v){
if (!cur || !v) return cur | v;
a[cur].ls = Merge(a[cur].ls, a[v].ls);
a[cur].rs = Merge(a[cur].rs, a[v].rs);
a[cur].v += a[v].v;
return cur;
}
int Query(int cur, int k){
if (a[cur].l == a[cur].r) return a[cur].l;
if (k <= LS.v) return Query(a[cur].ls, k);
else return Query(a[cur].rs, k - LS.v);
}
}t;
int f[maxn];
int getf(int x){return x == f[x] ? x : f[x] = getf(f[x]);}
int n, m, Q, p[maxn], link[maxn];
int main(){
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++){
scanf("%d", p + i);
t.rt[i] = ++t.tot; f[i] = i;
t.upd(t.rt[i], 1, n, p[i]);
link[p[i]] = i;
}
for (int u, v, i = 1; i <= m; i++){
scanf("%d%d", &u, &v);
int fu = getf(u), fv = getf(v);
t.Merge(t.rt[fu], t.rt[fv]);
f[fv] = fu;
}
scanf("%d", &Q);
while (Q--){
char opt[2]; int u, v;
scanf("%s", opt);
if (opt[0] == 'B'){
scanf("%d%d", &u, &v);
int fu = getf(u), fv = getf(v);
t.Merge(t.rt[fu], t.rt[fv]); f[fv] = fu;
}
if (opt[0] == 'Q'){
scanf("%d%d", &u, &v);
if (v > t.a[t.rt[getf(u)]].v) puts("-1");
else printf("%d\n", link[t.Query(t.rt[getf(u)], v)]);
}
}
return 0;
}